/**
 *
 * @author David
 */
import java.util.Vector;
import java.lang.Math;


public class State implements Comparable<State> {

        private String rep;
        private String goal;
        private Vector<String> path;
        private int depth;
        private int dist;
    private int searchType;

    //This state currently assumes an eight puzzle
    //Again, searchtype the int is here

    public State(String r, String g, int type) {
                rep = r;
                path = new Vector<String>();
                path.add(r);
                depth = 0;
                goal=g;
		searchType = type;

        }
        public State(State s, String n) {
	    //n is new or current state, s is the original state
                rep = n;
                path = new Vector<String>(s.path);
                path.add(n);
                depth = s.depth+1;
                goal=s.getGoal();
		searchType = s.getType();
        }
        public int printPath() {
                int count = 1;
		int d = 0;
                for (String step : path)
                {
		    //Prints the cost of each node (distance + heuristic)
                    System.out.println("F: "+(new State(step, goal, searchType).getF()+count));
		    System.out.println("Depth: " + d);
                    System.out.println(count+"\n"+convert(step));
		    d++;
                    count++;
                }
                return 0;
        }

        public int compareTo(State other) {

                if (!(other instanceof State)) {
                        System.exit(3);
                        return 0;
                }
    //These parts of the comparTo shouldn't be necessary 
    // deeper is larger: Depth first, Interative Deepening, AND IDA*
/*                else if((searchType== 2)||(searchType==3)||searchType==5){
		    return ((State)other).getDepth() -depth;
		}
                //deeper is smaller: Breadth First
                else if(searchType== 1){
		    return depth - ((State)other).getDepth();
		}*/
      
                //using H: A
		else {
			return getF() - ((State)other).getF();
		}
		System.out.println ("compareTo Error");
		return -1;

        }

        private String convert(String step) {
                String[] pieces = step.split("/");
                String answer = "";
                for (String p : pieces)
                        answer = answer +p +"\n";
                return answer;
        }
        public int getF(){
            return admisH()+depth;
        }

    public int admisH(){
	//returns the number of pieces that are out of place, ignoring the blank spot
	//assume string goal exists
	int count =0;
	for(int i =0; i<goal.length(); i++){
	    if((rep.charAt(i)!=goal.charAt(i))&&(rep.charAt(i)!='x')){
		count++;
	    }
	}
	return count;

    }

    //This function finds and adds the distances each piece is from its goal place. while interesting, its not an admissable heuristic
        public int getDist(){
            String p;
            String[] temp={rep.substring(0, 4), rep.substring(4,8), rep.substring(8)};
            String[] gtemp={goal.substring(0, 4), goal.substring(4,8), goal.substring(8)};
            int hor;
            int ver;
            for(int i=1; i<=8; i++){
                ver=0;
                hor=0;
                p=(new Integer(i)).toString();
                for(int j=0; j<temp.length; j++){
                    if(temp[j].indexOf(p)>=0){
                        hor=temp[j].indexOf(p);
                        ver=j;
//                        System.out.println(temp[j].indexOf(p));
//                        System.out.println(j);
                        break;
                    }
                }
                for(int j=0; j<gtemp.length; j++){
                    if(gtemp[j].indexOf(p)>=0){
                        hor=Math.abs(hor-gtemp[j].indexOf(p));
                        ver=Math.abs(ver-j);
//                        System.out.println(gtemp[j].indexOf(p));
//                        System.out.println(j);
                        break;
                    }
                }
//                System.out.println(p+": "+(hor+ver));
                dist+=hor+ver;
            }
//            System.out.println(goal+"\n"+dist);
//            System.exit(0);
            return dist;
        }
        public int getDepth() {
                return depth;
        }
        public void setDepth(int depth) {
                this.depth = depth;
        }
        public Vector<String> getPath() {
                return path;
        }

    public String getGoal(){
	return goal;
    }
        public void setPath(Vector<String> path) {
                this.path = path;
        }
        public String getRep() {
                return rep;
        }
        public void setRep(String rep) {
                this.rep = rep;
        }
    public int getType(){
	return searchType;
    }

}
